/**
 * <h3>CampusNewsServiceImpl</h3>
 * <p> 校园新闻服务实现类 </p>
 *
 * <h3>功能描述</h3>
 * <p> 实现了 {@link ICampusNewsService} 接口中定义的校园新闻信息增删改查业务逻辑 </p>
 * <p> 通过调用 {@link CampusNewsMapper} 完成对数据库的操作，支持条件查询、按ID查询、更新、新增和删除等操作 </p>
 *
 * <h3>元数据</h3>
 * <ul>
 *    <li> 作者：郭强</li>
 *    <li> 创建日期：2025年05月20日 21:20:00</li>
 * </ul>
 *
 * <h3>其他信息</h3>
 * <ul>
 *    <li> 参考链接：<a href="https://example.com">官方网页</a></li>
 *    <li> 示例代码：{@code new CampusNewsServiceImpl()} </li>
 * </ul>
 *
 * @apiNote 该类基于 MyBatis Plus 的 ServiceImpl 实现，需确保 CampusNewsMapper 正确注入
 * @implSpec 继承自 {@link ServiceImpl<CampusNewsMapper, CampusNewsDTO>} 并实现 {@link ICampusNewsService} 接口
 * @since 1.0.0
 */

package com.dnndo.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dnndo.common.core.domain.entity.SysRole;
import com.dnndo.common.core.domain.entity.SysUser;
import com.dnndo.system.domain.CampusNews;
import com.dnndo.system.domain.dto.CampusNewsDTO;
import com.dnndo.system.domain.dto.NewsDTO;
import com.dnndo.system.domain.vo.*;
import com.dnndo.system.mapper.CampusNewsMapper;
import com.dnndo.system.mapper.SysRoleMapper;
import com.dnndo.system.mapper.SysUserMapper;
import com.dnndo.system.service.ICampusNewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 校园新闻服务实现类
 */
@Service
public class CampusNewsServiceImpl extends ServiceImpl<CampusNewsMapper, CampusNewsDTO> implements ICampusNewsService {

    private final CampusNewsMapper campusNewsMapper;
    private final SysUserMapper sysUserMapper;
    private final SysRoleMapper sysRoleMapper;

    @Autowired
    public CampusNewsServiceImpl(CampusNewsMapper campusNewsMapper, SysUserMapper sysUserMapper, SysRoleMapper sysRoleMapper) {
        this.campusNewsMapper = campusNewsMapper;
        this.sysUserMapper = sysUserMapper;
        this.sysRoleMapper = sysRoleMapper;
    }

    /**
     * 查询符合条件的校园新闻列表
     * 逻辑说明：
     * 1. 首先获取当前用户的角色Key集合（如school、common、admin等）。
     * 2. 根据用户ID设置其所属学校ID到查询DTO中。
     * 3. 如果用户角色为school或common，则只能查询本校新闻（调用selectCampusNewsListSchool）。
     * 4. 如果用户角色为admin，则可查询所有新闻（调用selectCampusNewsList）。
     * 5. 返回最终查询结果。
     *
     * @param dto 封装查询条件的 CampusNews 对象，包含新闻标题、学校ID等过滤字段
     * @return List<CampusNews> 匹配条件的新闻信息列表
     * @see com.dnndo.system.mapper.CampusNewsMapper#selectCampusNewsList(CampusNewsDTO)
     */
    @Override
    public List<CampusNews> selectCampusNewsList(CampusNewsDTO dto) {
        List<CampusNews> campusNewsList = new ArrayList<>();
        // 获取当前用户的所有角色Key
        List<String> roleKeys = getUserRoleKeys(dto.getUserId());
        // 设置用户所属学校ID到DTO
        setUserSchoolId(dto);

        // 按角色分支查询
        if (roleKeys.contains("school") || roleKeys.contains("common")) {
            // 学校用户或普通用户只能查本校新闻
            campusNewsList = campusNewsMapper.selectCampusNewsListSchool(dto);
        } else if (roleKeys.contains("admin")) {
            // 管理员可查所有新闻
            campusNewsList = campusNewsMapper.selectCampusNewsList(dto);
        }
        return campusNewsList;
    }

    /**
     * 获取指定用户的权限角色Key集合
     *
     * @param userId 用户的唯一标识符
     * @return List<String> 用户所拥有的角色Key列表
     * @see com.dnndo.system.mapper.SysRoleMapper#selectRolePermissionByUserId(Long)
     */
    private List<String> getUserRoleKeys(Integer userId) {
        List<SysRole> roles = sysRoleMapper.selectRolePermissionByUserId(userId.longValue());
        return roles.stream().map(SysRole::getRoleKey).toList();
    }

    /**
     * 设置用户所属学校的ID到DTO中
     *
     * @param dto 包含用户ID的数据传输对象
     * @see com.dnndo.system.mapper.SysUserMapper#selectUserById(Long)
     */
    private void setUserSchoolId(CampusNewsDTO dto) {
        SysUser user = sysUserMapper.selectUserById(dto.getUserId().longValue());
        dto.setSchoolId(Integer.valueOf(user.getSchoolId()));
    }
    /**
     * 根据新闻ID查询新闻详细信息
     *
     * @param newsId 新闻ID，用于定位数据库中的唯一记录
     * @return CampusNewsDTO 新闻实体对象，若未找到则返回 null
     * @see com.dnndo.system.mapper.CampusNewsMapper#selectCampusNewsById(Integer)
     */
    @Override
    public CampusNewsDTO selectCampusNewsById(Long newsId) {
        return campusNewsMapper.selectCampusNewsById(Math.toIntExact(newsId));
    }

    /**
     * 更新指定ID的新闻信息
     *
     * @param campusNewsDTO 封装更新数据的 CampusNews 对象，必须包含有效的 newsId 字段
     * @return int 受影响的记录数，通常为 1 表示更新成功
     * @see com.dnndo.system.mapper.CampusNewsMapper#updateCampusNewsById(CampusNewsDTO)
     */
    @Override
    public int updateCampusNewsById(CampusNewsDTO campusNewsDTO) {
        return campusNewsMapper.updateCampusNewsById(campusNewsDTO);
    }

    /**
     * 新增一条新闻记录到数据库
     *
     * @param campusNewsDTO 封装新增数据的 CampusNews 对象，需确保字段完整性
     * @return int 受影响的记录数，通常为 1 表示插入成功
     * @see com.dnndo.system.mapper.CampusNewsMapper#insertCampusNews(CampusNewsDTO)
     */
    @Override
    public int insertCampusNews(CampusNewsDTO campusNewsDTO) {
        setUserSchoolId(campusNewsDTO);
        return campusNewsMapper.insertCampusNews(campusNewsDTO);
    }

    /**
     * 根据新闻ID删除对应的记录
     *
     * @param newsId 新闻唯一标识符
     * @return int 受影响的记录数，通常为 1 表示删除成功
     * @see com.dnndo.system.mapper.CampusNewsMapper#deleteCampusNewsById(Integer)
     */
    @Override
    public int deleteCampusNewsById(Integer newsId) {
        return campusNewsMapper.deleteCampusNewsById(newsId);
    }

    /**
     * 根据新闻id和语言获取新闻详细信息及相关资讯
     * 逻辑说明：
     * 1. 校验newsId参数是否合法。
     * 2. 根据语言类型分支：
     *    - zh：查询中文新闻详情及相关资讯列表，组装VO返回。
     *    - en：查询英文新闻详情及相关资讯列表，组装VO返回。
     *    - 其他：抛出参数异常。
     * 3. 捕获并包装所有异常，便于上层定位问题。
     *
     * @param newsId 新闻ID
     * @param language 语言类型（zh/en）
     * @return CampusNewsInfoVO 新闻详情及相关资讯
     */
    @Override
    public CampusNewsInfoVO selectCampusNewsByIdList(Integer newsId, String language) {
        if (newsId == null || newsId <= 0) {
            throw new IllegalArgumentException("新闻ID不能为空或小于等于0");
        }
        CampusNewsInfoVO result;
        CampusNewsInfoVOZH resultZH;
        CampusNewsInfoVOEN resultEN;
        try {
            List<CampusNewsInfoVOZHOtherNewsVOZH> otherNewsListZH;
            List<CampusNewsInfoVOZHOtherNewsVOEN> otherNewsListEN;
            if ("zh".equals(language)) {
                // 查询中文新闻详情及相关资讯
                resultZH = campusNewsMapper.selectCampusNewsByIdListZh(newsId);
                otherNewsListZH = campusNewsMapper.selectCampusNewsByIdCreatedAtZh(newsId);
                resultZH.setOtherNews(otherNewsListZH);
                result = resultZH;
            } else if ("en".equals(language)) {
                // 查询英文新闻详情及相关资讯
                resultEN = campusNewsMapper.selectCampusNewsByIdListEn(newsId);
                otherNewsListEN = campusNewsMapper.selectCampusNewsByIdCreatedAtEn(newsId);
                resultEN.setOtherNews(otherNewsListEN);
                result = resultEN;
            } else {
                // 不支持的语言类型
                throw new IllegalArgumentException("不支持的语言选项: " + language);
            }
        } catch (Exception e) {
            // 捕获所有异常并包装为运行时异常，便于上层统一处理
            throw new RuntimeException("查询校园新闻失败: " + e.getMessage(), e);
        }
        return result;
    }

    /**
     * 获取校园新闻列表（支持中英文）
     * 逻辑说明：
     * 1. 判断请求语言类型，若为英文则调用newsEn查询英文新闻列表。
     * 2. 否则默认查询中文新闻列表。
     * 3. 统一返回List<NewsVO>，便于前端适配。
     *
     * @param dto 查询参数，包含语言类型
     * @return List<NewsVO> 新闻列表
     */
    @Override
    public List<NewsVO> news(NewsDTO dto) {
        List<NewsVOZH> listZH;
        List<NewsVOEN> listEN;

        // 判断语言类型，分支查询
        if ("en".equalsIgnoreCase(dto.getLanguage())) {
            // 英文新闻
            listEN = campusNewsMapper.newsEn(dto);
            return new ArrayList<>(listEN);
        }
        // 默认中文新闻
        listZH = campusNewsMapper.news(dto);
        return new ArrayList<>(listZH);
    }

    //获取校园新闻总数
    @Override
    public int countCampusNews(NewsDTO dto) {
        return campusNewsMapper.countCampusNews(dto);
    }

}
